function [pca, pcaParams] = kneu_pca(pats,param,varargin)
% [pca, pcaParams] = kneu_pca(pats)
% get transformed data performing PCA with svd (that enables higher
% number of dimensions than samples)
% pats - data (nFeat X nSamples)
% [pca, pcaParams] = kneu_pca(pats,pcaParams,...)
% pcaParams - transformation params (set as empty if specifying number of
% components)
% options: 'method' - 'apply', 'inverse', use if params are available
%          'components' - number or fraction of components

method='';
nComponents=min(size(pats));
k=1;
while k<length(varargin),
    if ischar(varargin{k}),
        if strcmpi('method',lower(varargin{k})),
            method=varargin{k+1};
        end     
        if strcmpi('components',lower(varargin{k})),
            nComponents=varargin{k+1};
        end  
    else
        error('argument name must be a string');
    end
    k=k+2;
end

if isempty(method),
    % get centered train data: normalize the data to zero mean
    [pats,pcaParams.mean_ctp,pcaParams.std_ctp] = kneu_prestd(pats); 

    % PCA
    [pca ,pcaParams.transMat] = kneu_prepca(pats, nComponents);
else
    if strcmpi(method,'apply'),
        [pats] = kneu_trastd(pats,param.mean_ctp,param.std_ctp); 
        % transform normalized test data to PCA space
        pca = param.transMat*pats;
    elseif strcmpi(method,'inverse')
        % transform back to original space
        if size(param.transMat,1)==size(param.transMat,2)
            pats = inv(param.transMat)*pats;
        else
            pats = pinv(param.transMat)*pats;            
        end
        % renormalize
        pca = kneu_poststd(pats,param.mean_ctp,param.std_ctp);        
    else
        error('PCA method unknown.');
    end
    pcaParams = param;
end